struct per_user_data {
/* Notification ring, accessed via /dev/xen/evtchn. */
-#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
+#define EVTCHN_RING_SIZE (PAGE_SIZE / sizeof(evtchn_port_t))
#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
- u16 *ring;
+ evtchn_port_t *ring;
unsigned int ring_cons, ring_prod, ring_overflow;
/* Processes wait on this queue when ring is empty. */
if ((u = port_user[port]) != NULL) {
if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
- u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
+ u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port;
if (u->ring_cons == u->ring_prod++) {
wake_up_interruptible(&u->evtchn_wait);
kill_fasync(&u->evtchn_async_queue,
{
int rc;
unsigned int c, p, bytes1 = 0, bytes2 = 0;
- DECLARE_WAITQUEUE(wait, current);
struct per_user_data *u = file->private_data;
- add_wait_queue(&u->evtchn_wait, &wait);
+ /* Whole number of ports. */
+ count &= ~(sizeof(evtchn_port_t)-1);
- count &= ~1; /* even number of bytes */
-
- if (count == 0) {
- rc = 0;
- goto out;
- }
+ if (count == 0)
+ return 0;
if (count > PAGE_SIZE)
count = PAGE_SIZE;
for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
+ if (u->ring_overflow)
+ return -EFBIG;
if ((c = u->ring_cons) != (p = u->ring_prod))
break;
- if (u->ring_overflow) {
- rc = -EFBIG;
- goto out;
- }
-
- if (file->f_flags & O_NONBLOCK) {
- rc = -EAGAIN;
- goto out;
- }
-
- if (signal_pending(current)) {
- rc = -ERESTARTSYS;
- goto out;
- }
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
- schedule();
+ rc = wait_event_interruptible(
+ u->evtchn_wait, u->ring_cons != u->ring_prod);
+ if (rc)
+ return rc;
}
/* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
- sizeof(u16);
- bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
+ sizeof(evtchn_port_t);
+ bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t);
} else {
- bytes1 = (p - c) * sizeof(u16);
+ bytes1 = (p - c) * sizeof(evtchn_port_t);
bytes2 = 0;
}
if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
((bytes2 != 0) &&
- copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) {
- rc = -EFAULT;
- goto out;
- }
-
- u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
+ copy_to_user(&buf[bytes1], &u->ring[0], bytes2)))
+ return -EFAULT;
- rc = bytes1 + bytes2;
+ u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t);
- out:
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&u->evtchn_wait, &wait);
- return rc;
+ return bytes1 + bytes2;
}
static ssize_t evtchn_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
int rc, i;
- u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
+ evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
struct per_user_data *u = file->private_data;
if (kbuf == NULL)
return -ENOMEM;
- count &= ~1; /* even number of bytes */
+ /* Whole number of ports. */
+ count &= ~(sizeof(evtchn_port_t)-1);
if (count == 0) {
rc = 0;
}
spin_lock_irq(&port_user_lock);
- for (i = 0; i < (count/2); i++)
+ for (i = 0; i < (count/sizeof(evtchn_port_t)); i++)
if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
unmask_evtchn(kbuf[i]);
spin_unlock_irq(&port_user_lock);
memset(u, 0, sizeof(*u));
init_waitqueue_head(&u->evtchn_wait);
- if ((u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL)
- {
+ u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL);
+ if (u->ring == NULL) {
kfree(u);
return -ENOMEM;
}
free_page((unsigned long)u->ring);
- for (i = 0; i < NR_EVENT_CHANNELS; i++)
- {
+ for (i = 0; i < NR_EVENT_CHANNELS; i++) {
int ret;
if (port_user[i] != u)
continue;
spin_lock_init(&port_user_lock);
memset(port_user, 0, sizeof(port_user));
- /* (DEVFS) create '/dev/misc/evtchn'. */
+ /* Create '/dev/misc/evtchn'. */
err = misc_register(&evtchn_miscdev);
- if (err != 0)
- {
+ if (err != 0) {
printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
return err;
}
//the evtchn port for polling the notification,
//should be inputed as bochs's parameter
-uint16_t ioreq_remote_port, ioreq_local_port;
+evtchn_port_t ioreq_remote_port, ioreq_local_port;
//some functions to handle the io req packet
void sp_info()
ioreq_t* cpu_get_ioreq(void)
{
int rc;
- uint16_t port;
+ evtchn_port_t port;
rc = read(evtchn_fd, &port, sizeof(port));
if ((rc == sizeof(port)) && (port == ioreq_local_port)) {
// unmask the wanted port again
- write(evtchn_fd, &ioreq_local_port, 2);
+ write(evtchn_fd, &ioreq_local_port, sizeof(port));
//get the io packet from shared memory
return __cpu_get_ioreq();
#include <xen/linux/evtchn.h>
static int *xc_handle;
-static int virq_port;
+static evtchn_port_t virq_port;
int eventchn_fd = -1;
unsigned int domid;
/* Event channel port */
- uint16_t port;
+ evtchn_port_t port;
/* The remote end of the event channel, used only to validate
repeated domain introductions. */
- uint16_t remote_port;
+ evtchn_port_t remote_port;
/* The mfn associated with the event channel, used only to validate
repeated domain introductions. */
/* We scan all domains rather than use the information given here. */
void handle_event(void)
{
- uint16_t port;
+ evtchn_port_t port;
if (read(eventchn_fd, &port, sizeof(port)) != sizeof(port))
barf_perror("Failed to read from event fd");
char *vec[3];
unsigned int domid;
unsigned long mfn;
- uint16_t port;
+ evtchn_port_t port;
if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
send_error(conn, EINVAL);
static int dom0_init(void)
{
- int rc, fd, port;
+ int rc, fd;
+ evtchn_port_t port;
unsigned long mfn;
char str[20];
struct domain *dom0;
#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
#define __XEN_PUBLIC_EVENT_CHANNEL_H__
+typedef uint32_t evtchn_port_t;
+
/*
* EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
* accepting interdomain bindings from domain <remote_dom>. A fresh port
#define EVTCHNOP_alloc_unbound 6
typedef struct evtchn_alloc_unbound {
/* IN parameters */
- domid_t dom, remote_dom;
+ domid_t dom, remote_dom;
/* OUT parameters */
- uint32_t port;
+ evtchn_port_t port;
} evtchn_alloc_unbound_t;
/*
#define EVTCHNOP_bind_interdomain 0
typedef struct evtchn_bind_interdomain {
/* IN parameters. */
- domid_t remote_dom;
- uint32_t remote_port;
+ domid_t remote_dom;
+ evtchn_port_t remote_port;
/* OUT parameters. */
- uint32_t local_port;
+ evtchn_port_t local_port;
} evtchn_bind_interdomain_t;
/*
uint32_t virq;
uint32_t vcpu;
/* OUT parameters. */
- uint32_t port;
+ evtchn_port_t port;
} evtchn_bind_virq_t;
/*
#define BIND_PIRQ__WILL_SHARE 1
uint32_t flags; /* BIND_PIRQ__* */
/* OUT parameters. */
- uint32_t port;
+ evtchn_port_t port;
} evtchn_bind_pirq_t;
/*
typedef struct evtchn_bind_ipi {
uint32_t vcpu;
/* OUT parameters. */
- uint32_t port;
+ evtchn_port_t port;
} evtchn_bind_ipi_t;
/*
#define EVTCHNOP_close 3
typedef struct evtchn_close {
/* IN parameters. */
- uint32_t port;
+ evtchn_port_t port;
} evtchn_close_t;
/*
#define EVTCHNOP_send 4
typedef struct evtchn_send {
/* IN parameters. */
- uint32_t port;
+ evtchn_port_t port;
} evtchn_send_t;
/*
typedef struct evtchn_status {
/* IN parameters */
domid_t dom;
- uint32_t port;
+ evtchn_port_t port;
/* OUT parameters */
#define EVTCHNSTAT_closed 0 /* Channel is not in use. */
#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/
uint32_t vcpu; /* VCPU to which this channel is bound. */
union {
struct {
- domid_t dom;
+ domid_t dom;
} unbound; /* EVTCHNSTAT_unbound */
struct {
- domid_t dom;
- uint32_t port;
+ domid_t dom;
+ evtchn_port_t port;
} interdomain; /* EVTCHNSTAT_interdomain */
uint32_t pirq; /* EVTCHNSTAT_pirq */
uint32_t virq; /* EVTCHNSTAT_virq */
#define EVTCHNOP_bind_vcpu 8
typedef struct evtchn_bind_vcpu {
/* IN parameters. */
- uint32_t port;
+ evtchn_port_t port;
uint32_t vcpu;
} evtchn_bind_vcpu_t;